home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianPerspec.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
31KB
|
1,184 lines
/* ScianPerspec.c: John R. Murray, 3-30-90
creates and deals with perspective Controls
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianColors.h"
#include "ScianIDs.h"
#include "ScianWindows.h"
#include "ScianObjWindows.h"
#include "ScianErrors.h"
#include "ScianEvents.h"
#include "ScianScripts.h"
#include "ScianButtons.h"
#include "ScianPerspec.h"
#include "ScianArrays.h"
#include "ScianControls.h"
#include "ScianIcons.h"
#include "ScianDraw.h"
#include "ScianObjFunctions.h"
#include "ScianSnap.h"
/* globals */
ObjPtr perspecControlClass; /* class of perspecControl */
/* temporary defs to get something going */
/* none */
/* local constants */
#define MY_PI 3.14159
#define BUTTONHEIGHT 4 /* button "height"=width (pixels) of border) */
/* internal drawing things and fudges */
#define PERSPECBORDER 8.0
#define RECWIDTH 15.0
#define RECDEPTH 7.0
#define RECSIZE (RECDEPTH+RECWIDTH)
#define TOPFUDGE RECSIZE
#define SIDEFUDGE RECSIZE
#define BOTTOMFUDGE RECSIZE + 20.0
#define CLIPLINELENGTH 50.0
#define SLOP 30.0
#define ANGLESLOP 6.0
#define ORTHOSLOP ((MAXORTHOFOV - MINORTHOFOV) / 20.0)
#define PERSPECSCALE .1
#define MINCLIPDELTA 0.01
ObjPtr DrawPerspecControl(theControl)
ObjPtr theControl;
{
#ifdef GRAPHICS
int left, right, bottom, top;
ObjPtr theLabel;
char *label;
ObjPtr valuesArray, hilitesArray, locArray;
real values[4], hilites[4], loc[2];
real eyeDist, fov, nearClip, farClip;
Coord v[4][2];
real xPos, yPos;
int iX, iY;
real xRel, yRel;
real fudgeScale;
int color;
/* get bounds, and draw control background */
if (!Get2DIntBounds(theControl, &left, &right, &bottom, &top))
{
return NULLOBJ;
}
if (IsDrawingRestricted(left, right, bottom, top))
{
return ObjFalse;
}
valuesArray = GetFixedArrayVar("DrawPerspecControl", theControl,
VALUE, 1, 4L);
hilitesArray = GetFixedArrayVar("DrawPerspecControl", theControl,
HIGHLIGHTED, 1, 4L);
locArray = GetFixedArrayVar("DrawPerspecControl", theControl,
ICONLOC, 1, 2L);
if (!valuesArray || !hilitesArray || !locArray)
{
return NULLOBJ;
}
Array2CArray(values, valuesArray);
eyeDist = values[0];
fov = values[1];
nearClip = values[2];
farClip = values[3];
Array2CArray(hilites, hilitesArray);
Array2CArray(loc, locArray);
DrawRaisedRect(left, right, bottom, top, UIBACKGROUND);
/* draw everything else */
yPos = (int) (bottom + BOTTOMFUDGE
+ eyeDist * ((top - TOPFUDGE) - (bottom + BOTTOMFUDGE))
/ (MAXEYEDIST - MINEYEDIST));
xPos = (int) (left + (right - left) / 2);
iY = yPos;
iX = xPos;
if ((int) hilites[0])
{
SetUIColor(UIGRAY25);
}
else
{
SetUIColor(UITEXT);
}
/* Draw icon-like central figure */
#if 0
move2(xPos,yPos); /* center of figure */
rmv2(4.0, 4.0); /* +4, +4 */
rdr2(-RECWIDTH, 0.0); /* +4-RW, +4 */
rdr2(0.0, -RECWIDTH); /* +4-RW, +4-RW */
rdr2(RECWIDTH, 0.0); /* +4, +4-RW */
rdr2(0.0, RECWIDTH); /* +4, +4 */
rdr2(RECDEPTH, RECDEPTH); /* +4+RD, +4+RD */
rdr2(-RECWIDTH, 0.0); /* +4+RD-RW, +4+RD */
rdr2(0.0, -RECWIDTH); /* +4+RD-RW, +4+RD-RW */
rdr2(RECWIDTH, 0.0); /* +4+RD, +4+RD-RW */
rdr2(0.0, RECWIDTH); /* +4+RD, +4+RD */
rmv2(-RECWIDTH, 0.0); /* mmm +4+RD-RW, +4+RD */
rdr2(-RECDEPTH, -RECDEPTH); /* +4-RW, +4 */
rmv2(0.0, -RECWIDTH); /* mmm +4-RW, +4-RW */
rdr2(RECDEPTH, RECDEPTH); /* +4+RD-RW, +4+RD-RW */
rmv2(RECWIDTH, 0.0); /* mmm +4+RD, +4+RD-RW */
rdr2(-RECDEPTH, -RECDEPTH); /* +4, +4-RW */
#else
iX += 4;
iY += 4;
DrawLine(iX, iY, iX, iY - RECWIDTH);
DrawLine(iX - RECWIDTH, iY, iX - RECWIDTH, iY - RECWIDTH);
DrawLine(iX, iY, iX - RECWIDTH, iY);
DrawLine(iX, iY - RECWIDTH, iX - RECWIDTH, iY - RECWIDTH);
DrawLine(iX + RECDEPTH, iY + RECDEPTH, iX + RECDEPTH, iY + RECDEPTH - RECWIDTH);
DrawLine(iX + RECDEPTH - RECWIDTH, iY + RECDEPTH, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH - RECWIDTH);
DrawLine(iX + RECDEPTH, iY + RECDEPTH, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH);
DrawLine(iX + RECDEPTH, iY + RECDEPTH - RECWIDTH, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH - RECWIDTH);
DrawLine(iX, iY, iX + RECDEPTH, iY + RECDEPTH);
DrawLine(iX - RECWIDTH, iY, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH);
DrawLine(iX - RECWIDTH, iY - RECWIDTH, iX + RECDEPTH - RECWIDTH, iY + RECDEPTH - RECWIDTH);
DrawLine(iX, iY - RECWIDTH, iX + RECDEPTH, iY + RECDEPTH - RECWIDTH);
#endif
/* Draw near-clip and far-clip lines */
yPos = (int) (bottom + BOTTOMFUDGE
+ nearClip * ((top - TOPFUDGE) - (bottom + BOTTOMFUDGE))
/ (MAXEYEDIST - MINEYEDIST));
xPos = (int) (left + (right - left) / 2);
iX = xPos;
iY = yPos;
if ((int) hilites[2])
{
SetUIColor(UIGRAY12);
}
else
{
SetUIColor(UITEXT);
}
#if 0
move2(xPos, yPos);
rmv2(-CLIPLINELENGTH/2, 0.0);
rdr2(CLIPLINELENGTH, 0.0);
if ((int) hilites[2])
{
rmv2(0,1);
rdr2(-CLIPLINELENGTH, 0);
rmv2(0,-2);
rdr2(CLIPLINELENGTH, 0);
}
#else
DrawLine(iX - CLIPLINELENGTH/2, iY, iX + CLIPLINELENGTH/2, iY);
if ((int) hilites[2])
{
DrawLine(iX - CLIPLINELENGTH/2, iY+1, iX + CLIPLINELENGTH/2, iY+1);
DrawLine(iX - CLIPLINELENGTH/2, iY-1, iX + CLIPLINELENGTH/2, iY-1);
}
#endif
yPos = (int) (bottom + BOTTOMFUDGE
+ farClip * ((top - TOPFUDGE) - (bottom + BOTTOMFUDGE))
/ (MAXEYEDIST - MINEYEDIST));
xPos = (int) (left + (right - left) / 2);
iX = xPos;
iY = yPos;
if ((int) hilites[3])
{
SetUIColor(UIGRAY12);
}
else
{
SetUIColor(UITEXT);
}
#if 0
move2(xPos, yPos);
rmv2(-CLIPLINELENGTH/2, 0.0);
rdr2(CLIPLINELENGTH, 0.0);
if ((int) hilites[3])
{
rmv2(0,1);
rdr2(-CLIPLINELENGTH, 0);
rmv2(0,-2);
rdr2(CLIPLINELENGTH, 0);
}
#else
DrawLine(iX - CLIPLINELENGTH/2, iY, iX + CLIPLINELENGTH/2, iY);
if ((int) hilites[3])
{
DrawLine(iX - CLIPLINELENGTH/2, iY+1, iX + CLIPLINELENGTH/2, iY+1);
DrawLine(iX - CLIPLINELENGTH/2, iY-1, iX + CLIPLINELENGTH/2, iY-1);
}
#endif
/* Draw field-of-view lines */
if ((int) hilites[1])
{
SetUIColor(UIGRAY12);
}
else
{
SetUIColor(UITEXT);
}
/* (((b[1]-SF)-(b[0]+SF))/2.0)) * fov / MAXO = mX-(b[0]+b[1])/2.0 */
if (GetPredicate(theControl, ORTHO))
{
real xOff;
/*draw width of ortho view lines */
xOff = fov / MAXORTHOFOV * ((right - SIDEFUDGE) - (left + SIDEFUDGE)) / 2.0;
#if 0
move2((left + right) / 2 + xOff, bottom + BOTTOMFUDGE);
draw2((left + right) / 2 + xOff, top - TOPFUDGE);
#else
DrawLine((left + right) / 2 + xOff, bottom + BOTTOMFUDGE,
(left + right) / 2 + xOff, top - TOPFUDGE);
#endif
if ((int) hilites[1])
{
#if 0
move2((left + right) / 2 + xOff + 1, bottom + BOTTOMFUDGE);
draw2((left + right) / 2 + xOff + 1, top - TOPFUDGE);
#else
DrawLine((left + right) / 2 + xOff + 1, bottom + BOTTOMFUDGE,
(left + right) / 2 + xOff + 1, top - TOPFUDGE);
#endif
}
#if 0
move2((left + right) / 2 - xOff, bottom + BOTTOMFUDGE);
draw2((left + right) / 2 - xOff, top - TOPFUDGE);
#else
DrawLine((left + right) / 2 - xOff, bottom + BOTTOMFUDGE,
(left + right) / 2 - xOff, top - TOPFUDGE);
#endif
if ((int) hilites[1])
{
#if 0
move2((left + right) / 2 - xOff - 1, bottom + BOTTOMFUDGE);
draw2((left + right) / 2 - xOff - 1, top - TOPFUDGE);
#else
DrawLine((left + right) / 2 - xOff - 1, bottom + BOTTOMFUDGE,
(left + right) / 2 - xOff - 1, top - TOPFUDGE);
#endif
}
}
else
{
/* draw angle of perspective view lines */
xPos = (int) (left + (right - left) / 2);
yPos = (int) (bottom + BOTTOMFUDGE);
#if 0
move2(xPos, yPos);
#endif
xRel = rsin(MY_PI * (fov/2.0)/180.0);
yRel = rcos(MY_PI * (fov/2.0)/180.0);
if (xRel / yRel >= ((right - PERSPECBORDER) - xPos)
/ ((top - PERSPECBORDER) - yPos))
{
fudgeScale = ((right - PERSPECBORDER) - xPos) / xRel;
xRel = xRel * fudgeScale; /* should end up being xPos - left */
yRel = yRel * fudgeScale;
}
else
{
fudgeScale = ((top - PERSPECBORDER) - yPos) / yRel;
yRel = yRel * fudgeScale;
xRel = xRel * fudgeScale;
}
#if 0
rdr2(xRel, yRel);
if ((int) hilites[1])
{
rmv2(1,0);
rdr2(-xRel, -yRel);
}
move2(xPos, yPos);
rdr2(-xRel, yRel);
if ((int) hilites[1])
{
rmv2(-1,0);
rdr2(xRel, -yRel);
}
#else
if ((int) hilites[1])
{
SetLineWidth(2);
}
DrawLine(xPos, yPos, xPos + xRel, yPos + yRel);
DrawLine(xPos, yPos, xPos - xRel, yPos + yRel);
if ((int) hilites[1])
{
SetLineWidth(1);
}
#endif
}
if (GetVar(theControl, COLOR))
{
color = GetInt(GetIntVar("DrawIconButtonObj", theControl, COLOR));
}
else
{
color = UIBACKGROUND;
}
if (GetVar(theControl, LABEL))
{
label = GetString(GetStringVar("DrawIconButtonObj", theControl, LABEL));
}
else
{
label = (char *) NIL;
}
/* Draw the Eye */
DrawIcon((left + right) / 2 + loc[0], bottom + BOTTOMFUDGE/2.0 + loc[1],
GetInt(GetIntVar("DrawIconButtonObj", theControl, WHICHICON)),
label, (char *) NIL, color,
DI_DRAWFORE | DI_DRAWBACK | DI_SMALLTEXT);
return NULLOBJ;
#endif /* GRAPHICS */
}
void Eyeball(left, right, bottom, top, xPos, yPos)
int left, right, bottom, top;
real xPos, yPos;
{
#ifdef GRAPHICS
#if 0
/* Draw THE EYEBALL!!! */
xPos = left + (right - left) / 2;
yPos = bottom + BOTTOMFUDGE/2.0;
SetUIColor(UITEXT);
move2(xPos, yPos);
rdr2(1,0);
rdr2(0,1);
rdr2(-1, 0);
rdr2(0,-1);
rmv2(-1,-1);
rdr2(1,-1);
rdr2(1, 0);
rdr2(2, 2);
rdr2(0, 1);
rdr2(-2,2);
rdr2(-1,0);
rdr2(-2,-2);
rdr2(0,-1);
rmv2(0,4);
rdr2(-2, -2);
rdr2(0, -3);
rdr2(3,-3);
rdr2(3,0);
rdr2(3,3);
rdr2(0,3);
rdr2(-2,2);
rdr2(0,4);
rdr2(-5,0);
rdr2(0,-4);
rmv2(-3,0);
rdr2(11,0);
SetUIColor(UIRED);
move2(xPos - 1, yPos + 3);
rdr2(-2,-2);
rdr2(0,-1);
rdr2(3,-3);
rdr2(1,0);
rdr2(3,3);
rdr2(0,1);
rdr2(-2,2);
rdr2(1,0);
rdr2(0,-3);
rdr2(-2,-2);
rdr2(-3,0);
rdr2(-2,2);
rdr2(0,3);
rdr2(1,1);
#endif
#endif /* GRAPHICS */
}
ObjPtr PressPerspecControl(theControl, mouseX, mouseY, flags)
ObjPtr theControl;
int mouseX, mouseY;
int flags;
{
#ifdef INTERACTIVE
int mX, mY, mXold, mYold; /* mouse X and Y returned by Mouse()*/
int deltaX, deltaY; /* change from initial X and Y */
int bounds[4]; /* meat of boundsArray */
ObjPtr valuesArray; /* array of data for complex control */
real values[4]; /* meat of valuesArray */
real oldValues[4]; /* old meat of valuesArray */
real saveValues[4]; /* old meat of valuesArray */
int isChanged; /* return value of changer */
ObjPtr hilitesArray; /* ptr to hilites values for parts */
real hilites[4]; /* meat of hilites values array */
int i; /* loop counter */
int which; /* which control part we're moving */
real tempvalue; /* temp. holder for value swapping */
real nearYPos, farYPos; /* calculation temporaries */
Bool ortho; /* value of GetPredicate(obj, ORTHO) */
Bool hiResMode = false; /* true iff user wants hi mouse res. */
real clipOff1, clipOff2; /* offsets of clip planes from object*/
if (!Get2DIntBounds(theControl,&bounds[0],&bounds[1],&bounds[2],&bounds[3]))
{
return ObjFalse;
}
valuesArray = GetFixedArrayVar("PressPerspecControl",theControl,VALUE,1,4L);
hilitesArray = GetFixedArrayVar("PressPerspecControl",theControl,HIGHLIGHTED,1,4L);
if (valuesArray && hilitesArray)
{
Array2CArray(values, valuesArray);
Array2CArray(hilites, hilitesArray);
}
else
{
return ObjFalse;
}
/* test if mouse in my rectangle */
if (mouseX < bounds[0] || mouseX > bounds[1] ||
mouseY < bounds[2] || mouseY > bounds[3])
{
/* mouse out of my rectangle, do nothing, return */
return ObjFalse;
}
/* test for helpclick */
if (TOOL(flags) == T_HELP)
{
ContextHelp(theControl);
return ObjTrue;
}
/* it's really a click, and not out of bounds, and not a helpclick */
SaveForUndo(theControl);
if (ShiftDown())
{
hiResMode = true;
}
for (i=0; i<4; ++i)
saveValues[i] = oldValues[i] = values[i];
ortho = GetPredicate(theControl, ORTHO);
/* determine which part is moving */
if (ABS(mouseX - (bounds[0] + bounds[1])/2) < RECSIZE/2
&& ABS(mouseY - (bounds[2] + BOTTOMFUDGE
+ values[0] * ((bounds[3]-TOPFUDGE) - (bounds[2]+BOTTOMFUDGE))
/ (MAXEYEDIST - MINEYEDIST))) < RECSIZE/2)
{
/* changing the eyeDistance */
which = 0;
clipOff1 = values[2] - values[0];
clipOff2 = values[3] - values[0];
}
else if (ortho && ORTHOSLOP >
ABS(values[1] - ABS(MAXORTHOFOV *
(mouseX - (bounds[0] + bounds[1])/2.0)
/ ( ((bounds[1]-SIDEFUDGE)-(bounds[0]+SIDEFUDGE)) / 2.0))))
{
/* changing the orthogonal field of view */
which = 1;
}
else if (ABS(values[1] - ABS(2.0 * 180.0 * ratan2(mouseX - (bounds[1] + bounds[0]) / 2.0,
mouseY - (bounds[2] + BOTTOMFUDGE)) / MY_PI)) < ANGLESLOP)
{
/* changing the perspective angle of view */
which = 1;
}
else /* default to moving the nearest clipping plane */
{
nearYPos = (int) (bounds[2] + BOTTOMFUDGE
+ values[2] * ((bounds[3] - TOPFUDGE) - (bounds[2] + BOTTOMFUDGE))
/ (MAXEYEDIST - MINEYEDIST));
farYPos = (int) (bounds[2] + BOTTOMFUDGE
+ values[3] * ((bounds[3] - TOPFUDGE) - (bounds[2] + BOTTOMFUDGE))
/ (MAXEYEDIST - MINEYEDIST));
if (ABS(mouseY - nearYPos) < ABS(mouseY - farYPos))
{
which = 2;
if (ABS(mouseY - nearYPos) > 3)
/* if more than 3 pixels away, snap line there */
{
saveValues[2] = (mouseY - (bounds[2] + BOTTOMFUDGE))
/ (((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE))
/ (MAXCLIP - MINCLIP) ) + MINCLIP;
}
}
else
{
which = 3;
if (ABS(mouseY - farYPos) > 3)
/* more than 3 pixels, snap */
{
saveValues[3] = (mouseY - (bounds[2] + BOTTOMFUDGE))
/ (((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE))
/ (MAXCLIP - MINCLIP) ) + MINCLIP;
}
}
}
SetVar(theControl, CURRENT, NewInt(which));
MakeMeCurrent(theControl);
mXold = -1;
mYold = -1;
/* track mouse */
while (Mouse(&mX, &mY))
{
/* if new values identical to old values, do squat */
if (mX == mXold && mY == mYold)
{
continue;
}
mXold = mX;
mYold = mY;
if (hiResMode != ShiftDown())
/* state of shift-key changed */
{
hiResMode = ShiftDown();
for (i=0; i<4; ++i)
{
saveValues[i] = values[i];
}
mouseX = mX;
mouseY = mY;
}
#if 0
if (mX < bounds[0] - SLOP || mX > bounds[1] + SLOP /* mouse outside rectangle */
|| mY < bounds[2] - SLOP || mY > bounds[3] + SLOP)
#else
/* based only on x axis */
if (mX < bounds[0] - SLOP || mX > bounds[1] + SLOP)
#endif
{
/* unhighlight here */
if ((int) hilites[which])
{
hilites[which] = false;
}
if (values[which] != oldValues[which])
{
for (i=0; i<4; ++i)
values[i] = oldValues[i];
}
}
else /* mouse inside rectangle */
{
/* highlight here */
if(! (int) hilites[which])
{
hilites[which] = true;
hilitesArray = NewRealArray(1, (long) 4);
CArray2Array(hilitesArray, hilites);
SetVar(theControl, HIGHLIGHTED, hilitesArray);
}
deltaX = mX - mouseX;
deltaY = mY - mouseY;
switch(which)
{
case 0:
values[0] = saveValues[0] + deltaY / (((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE))
/ (MAXEYEDIST - MINEYEDIST));
values[2] = values[0] + clipOff1;
values[3] = values[0] + clipOff2;
if (hiResMode)
{
values[0] = saveValues[0]+(values[0]-saveValues[0])/10;
values[2] = saveValues[2]+(values[2]-saveValues[2])/10;
values[3] = saveValues[3]+(values[3]-saveValues[3])/10;
}
if (values[0] < MINEYEDIST)
values[0] = MINEYEDIST;
if (values[0] > MAXEYEDIST)
values[0] = MAXEYEDIST;
if (values[2] < MINCLIP)
values[2] = MINCLIP;
if (values[2] > MAXCLIP)
values[2] = MAXCLIP;
if (values[3] < MINCLIP)
values[3] = MINCLIP;
if (values[3] > MAXCLIP)
values[3] = MAXCLIP;
break;
case 1:
if (ortho)
{
values[1] = ABS(MAXORTHOFOV *
(mX - (bounds[0] + bounds[1])/2.0)
/ ( ((bounds[1]-SIDEFUDGE)-(bounds[0]+SIDEFUDGE)) / 2.0));
if (hiResMode)
values[1]=saveValues[1]+(values[1]-saveValues[1])/10;
if (values[1] < MINORTHOFOV)
values[1] = MINORTHOFOV;
if (values[1] > MAXORTHOFOV)
values[1] = MAXORTHOFOV;
}
else
{
values[1] = 2.0 * 180.0 * ratan2(mX - (bounds[1] + bounds[0]) / 2.0,
mY - (bounds[2] + BOTTOMFUDGE)) / MY_PI;
values[1] = values[1] < 0.0 ? -values[1] : values[1];
if (hiResMode)
values[1]=saveValues[1]+(values[1]-saveValues[1])/10;
if (values[1] < MINAOV)
values[1] = MINAOV;
if (values[1] > MAXAOV)
values[1] = MAXAOV;
}
break;
case 2:
values[2] = saveValues[2] + deltaY / (((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE))
/ (MAXCLIP - MINCLIP));
if (hiResMode)
values[2] = saveValues[2]+(values[2]-saveValues[2])/10;
if (values[2] < MINCLIP)
values[2] = MINCLIP;
if (values[2] > MAXCLIP - MINCLIPDELTA)
values[2] = MAXCLIP - MINCLIPDELTA;
break;
case 3:
values[3] = saveValues[3] + deltaY / (((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE))
/ (MAXCLIP - MINCLIP));
if (hiResMode)
values[3] = saveValues[3] + (values[3]-saveValues[3])/10;
if (values[3] < MINCLIP + MINCLIPDELTA)
values[3] = MINCLIP + MINCLIPDELTA;
if (values[3] > MAXCLIP)
values[3] = MAXCLIP;
break;
default:
ReportError("PressPerspecControl", "internal error!");
break;
}
}
/* if clip planes reversed, fix 'em */
if (values[3] < values[2])
{
tempvalue = values[2]; /* swap values */
values[2] = values[3];
values[3] = tempvalue;
tempvalue = hilites[2]; /* swap hilite flags */
hilites[2] = hilites[3];
hilites[3] = tempvalue;
tempvalue = oldValues[2]; /* swap old values, too */
oldValues[2] = oldValues[3];
oldValues[3] = tempvalue;
tempvalue = saveValues[2]; /* ..and the saved values */
saveValues[2] = saveValues[3];
saveValues[3] = tempvalue;
if (which == 3)
{
which = 2; /* switch to other control part */
}
else if (which == 2)
{
which = 3;
}
SetVar(theControl, CURRENT, NewInt(which));
}
if (values[3] - values[2] < MINCLIPDELTA)
{
if (values[2] < MINCLIP + MINCLIPDELTA)
{
values[3] = values[2] + MINCLIPDELTA;
}
else if (values[3] > MAXCLIP - MINCLIPDELTA)
{
values[2] = values[3] - MINCLIPDELTA;
}
else
{
real ctr;
ctr = (values[3] + values[2]) / 2.0;
values[2] = ctr - MINCLIPDELTA / 2.0;
values[3] = ctr + MINCLIPDELTA / 2.0;
}
}
valuesArray = NewRealArray (1, (long) 4);
CArray2Array(valuesArray, values);
SetVar(theControl, VALUE, valuesArray);
hilitesArray = NewRealArray (1, (long) 4);
CArray2Array(hilitesArray, hilites);
SetVar(theControl, HIGHLIGHTED, hilitesArray);
DrawMe(theControl);
ChangedValue(theControl);
}
hilites[0] = false;
hilites[1] = false;
hilites[2] = false;
hilites[3] = false;
hilitesArray = NewRealArray(1, (long) 4);
CArray2Array(hilitesArray, hilites);
SetVar(theControl, HIGHLIGHTED, hilitesArray);
ImInvalid(theControl);
ChangedValue(theControl);
if (logging) LogControl(theControl);
return ObjTrue;
#endif /* INTERACTIVE */
}
ObjPtr KeyDownPerspecControl(theControl, key, flags)
/* KEYDOWN event for PerspecControls */
ObjPtr theControl;
int key;
long flags;
{
#ifdef INTERACTIVE
int bounds[4]; /* meat of boundsArray */
ObjPtr valuesArray; /* array of data for complex control */
real values[4]; /* meat of valuesArray */
real oldValues[4]; /* old meat of valuesArray */
int isChanged; /* return value of changer */
ObjPtr theWhich; /* Int thing holding which control */
int which; /* which control part we're moving */
if (!AmICurrent(theControl))
{
return ObjFalse;
}
/* BORK temporary kludge */
theWhich = GetIntVar("KeyDownPerspecControl", theControl, CURRENT);
if (!theWhich)
{
/* can't find what part is current */
return ObjFalse;
}
which = GetInt(theWhich);
if (which < 0 || which > 3)
{
/* CURRENT value was invalid */
return ObjFalse;
}
if (!Get2DIntBounds(theControl,&bounds[0],&bounds[1],&bounds[2],&bounds[3]))
{
return NULLOBJ;
}
valuesArray = GetFixedArrayVar("KeyDownPerspecControl", theControl, VALUE, 1, 4L);
if (valuesArray)
{
Array2CArray(values, valuesArray);
}
else
{
return ObjFalse;
}
switch(key)
{
case '\0':
if (logging) LogControl(theControl);
return ObjTrue;
break;
case FK_UP_ARROW:
case FK_RIGHT_ARROW:
switch(which)
{
case 0:
values[0] = values[0] + PERSPECSCALE
* (MAXEYEDIST - MINEYEDIST)
/ ((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE));
if (values[0] < MINEYEDIST)
values[0] = MINEYEDIST;
if (values[0] > MAXEYEDIST)
values[0] = MAXEYEDIST;
break;
case 1:
if (GetPredicate(theControl, ORTHO))
{
values[1] = values[1] + 0.2;
if (values[1] < MINORTHOFOV)
values[1] = MINORTHOFOV;
if (values[1] > MAXORTHOFOV)
values[1] = MAXORTHOFOV;
}
else
{
values[1] = values[1] + 0.5;
if (values[1] < MINAOV)
values[1] = MINAOV;
if (values[1] > MAXAOV)
values[1] = MAXAOV;
}
break;
case 2:
values[2] = values[2] + PERSPECSCALE
* (MAXEYEDIST - MINEYEDIST)
/ ((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE));
if (values[2] < MINCLIP)
values[2] = MINCLIP;
if (values[2] > MAXCLIP)
values[2] = MAXCLIP;
break;
case 3:
values[3] = values[3] + PERSPECSCALE
* (MAXEYEDIST - MINEYEDIST)
/ ((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE));
if (values[3] < MINCLIP)
values[3] = MINCLIP;
if (values[3] > MAXCLIP)
values[3] = MAXCLIP;
break;
default:
ReportError("KeyDownPerspecControl", "internal error!");
break;
}
break;
case FK_DOWN_ARROW:
case FK_LEFT_ARROW:
switch(which)
{
case 0:
values[0] = values[0] - PERSPECSCALE
* (MAXEYEDIST - MINEYEDIST)
/ ((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE));
if (values[0] < MINEYEDIST)
values[0] = MINEYEDIST;
if (values[0] > MAXEYEDIST)
values[0] = MAXEYEDIST;
break;
case 1:
if (GetPredicate(theControl, ORTHO))
{
values[1] = values[1] - 0.2;
if (values[1] < MINORTHOFOV)
values[1] = MINORTHOFOV;
if (values[1] > MAXORTHOFOV)
values[1] = MAXORTHOFOV;
}
else
{
values[1] = values[1] - 0.5;
if (values[1] < MINAOV)
values[1] = MINAOV;
if (values[1] > MAXAOV)
values[1] = MAXAOV;
}
break;
case 2:
values[2] = values[2] - PERSPECSCALE
* (MAXEYEDIST - MINEYEDIST)
/ ((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE));
if (values[2] < MINCLIP)
values[2] = MINCLIP;
if (values[2] > MAXCLIP)
values[2] = MAXCLIP;
break;
case 3:
values[3] = values[3] - PERSPECSCALE
* (MAXEYEDIST - MINEYEDIST)
/ ((bounds[3] - TOPFUDGE)
- (bounds[2] + BOTTOMFUDGE));
if (values[3] < MINCLIP)
values[3] = MINCLIP;
if (values[3] > MAXCLIP)
values[3] = MAXCLIP;
break;
default:
ReportError("KeyDownPerspecControl", "internal error");
break;
}
break;
default:
if (F_SHIFTDOWN & flags)
{
MakePerspecOrtho(theControl, !GetPredicate(theControl, ORTHO));
}
return ObjTrue; /* acknowledge call, but ignore key */
break;
}
CArray2Array(valuesArray, values);
ImInvalid(theControl);
ChangedValue(theControl);
return ObjTrue;
#endif /* INTERACTIVE */
}
ObjPtr SetPerspecControlValue(theControl, theNewValues)
/* sets values on perspective control */
ObjPtr theControl, theNewValues;
{
ObjPtr theOldValues;
real newValues[4], temp;
real oldValues[4];
int changed;
int i;
changed = false;
theOldValues = GetVar(theControl, VALUE);
if (!theOldValues)
{
changed = true;
}
else if (!IsArray(theOldValues))
{
changed = true;
}
else
{
Array2CArray(oldValues, theOldValues);
}
Array2CArray(newValues, theNewValues);
newValues[0] = newValues[0] < MINEYEDIST ? MINEYEDIST : newValues[0];
newValues[0] = newValues[0] > MAXEYEDIST ? MAXEYEDIST : newValues[0];
if (GetPredicate(theControl, ORTHO))
{
newValues[1] = newValues[1] < MINORTHOFOV ? MINORTHOFOV : newValues[1];
newValues[1] = newValues[1] > MAXORTHOFOV ? MAXORTHOFOV : newValues[1];
}
else
{
newValues[1] = newValues[1] < MINAOV ? MINAOV : newValues[1];
newValues[1] = newValues[1] > MAXAOV ? MAXAOV : newValues[1];
}
newValues[2] = newValues[2] < MINCLIP ? MINCLIP : newValues[2];
newValues[2] = newValues[2] > MAXCLIP ? MAXCLIP : newValues[2];
newValues[3] = newValues[3] < MINCLIP ? MINCLIP : newValues[3];
newValues[3] = newValues[3] > MAXCLIP ? MAXCLIP : newValues[3];
if (newValues[2] > newValues[3])
{
temp = newValues[2];
newValues[2] = newValues[3];
newValues[3] = temp;
}
for (i = 0; !changed && i < 4; ++i)
{
if (newValues[i] != oldValues[i])
changed = true;
}
CArray2Array(theNewValues, newValues);
SetVar(theControl, VALUE, theNewValues);
if (changed)
{
ImInvalid(theControl);
ChangedValue(theControl);
if (logging) LogControl(theControl);
return ObjTrue;
}
if (logging) LogControl(theControl);
return ObjFalse;
}
ObjPtr GetPerspecControlValue(theControl, values)
ObjPtr theControl;
real values[4];
{
ObjPtr theValues;
int i;
theValues = GetFixedArrayVar("GetPerspecControlValue", theControl, VALUE, 1, 4L);
if (!theValues)
{
for (i=0;i<4;++i) values[i] = 0.0;
return ObjFalse;
}
/* successful retrieval of values */
Array2CArray(values, theValues);
return ObjTrue;
}
#ifdef PROTO
Bool MakePerspecOrtho(ObjPtr control, Bool flag)
#else
Bool MakePerspecOrtho(control, flag)
ObjPtr control;
Bool flag;
#endif
{
if (flag != GetPredicate(control, ORTHO))
{
ObjPtr valsArray;
real vals[4];
real dist, fov; /* object distance, field of view */
ObjPtr oldValue;
SetVar(control, ORTHO, flag ? ObjTrue : ObjFalse);
valsArray = GetFixedArrayVar("MakePerspecOrtho", control, VALUE, 1, 4L);
Array2CArray(vals, valsArray);
dist = vals[0];
fov = vals[1];
if (flag)
{
/* if control was perspec, is now ORTHO */
/* obsolete?
fov = (dist / rcos((fov / 2.0) * (MY_PI / 180.0)))
* rsin((fov / 2.0) * (MY_PI / 180.0));
*/
oldValue = GetVar(control, OLDVALUE);
if (oldValue)
{
fov = GetReal(oldValue);
}
else
{
fov = INITFOV;
}
if (fov < 0.0)
fov = -fov;
if (fov > MAXORTHOFOV)
fov = MAXORTHOFOV;
}
else
{
/* control was ORTHO, is now perspec again */
oldValue = GetVar(control, OLDVALUE);
if (oldValue)
{
fov = GetReal(oldValue);
}
else
{
fov = INITAOV;
}
}
SetVar(control, OLDVALUE, NewReal(vals[1]));
vals[1] = fov;
CArray2Array(valsArray, vals);
ChangedValue(control);
ImInvalid(control);
return true;
}
else
{
return false;
}
}
void InitPerspecControls()
/* sets up perspective controls stuff */
{
perspecControlClass = NewObject(controlClass, 0);
AddToReferenceList((ThingPtr) perspecControlClass);
SetMethod(perspecControlClass, DRAW, DrawPerspecControl);
SetMethod(perspecControlClass, PRESS, PressPerspecControl);
SetMethod(perspecControlClass, SETVAL, SetPerspecControlValue);
SetMethod(perspecControlClass, GETVAL, GetPerspecControlValue);
SetMethod(perspecControlClass, KEYDOWN, KeyDownPerspecControl);
SetVar(perspecControlClass, COLOR, NewInt(UIBACKGROUND));
SetVar(perspecControlClass, WHICHICON, NewInt(ICONOBSERVER));
SetVar(perspecControlClass, TYPESTRING, NewString("perspective control"));
SetVar(perspecControlClass, HELPSTRING, NewString(
"This control affects the perspective view in the Space. Clicking and \
dragging the central cube object will move the viewed fields towards or \
away from the Eye. You can move the front and back clipping planes by \
clicking on and dragging the two horizontal lines. Clicking and \
dragging either of the two diagonal lines will change the angle of view."));
}
void KillPerspecControls()
/* unsets-up perspective controls stuff */
{
RemoveFromReferenceList(perspecControlClass);
perspecControlClass = 0;
}
#define XFUDGE -4.0
#define YFUDGE -7.0
ObjPtr NewPerspecControl(left, right, bottom, top, name)
int left, right, bottom, top;
char *name;
/*Makes a new panel with bounds left, right, bottom, top, and label label*/
{
real values[4], hilites[4];
ObjPtr valuesArray, hilitesArray;
ObjPtr retVal;
ObjPtr labelPtr;
ObjPtr hilightPtr;
real loc[2];
ObjPtr locArray;
values[0] = INITEYEDIST;
values[1] = INITAOV;
values[2] = INITNEARCLIP;
values[3] = INITFARCLIP;
hilites[0] = false;
hilites[1] = false;
hilites[2] = false;
hilites[3] = false;
loc[0] = XFUDGE;
loc[1] = YFUDGE;
valuesArray = NewRealArray(1, (long) 4);
hilitesArray = NewRealArray(1, (long) 4);
locArray = NewRealArray(1, (long) 2);
retVal = NewObject(perspecControlClass, 0);
if (valuesArray && hilitesArray && retVal)
{
CArray2Array(valuesArray, values);
SetVar(retVal, VALUE, (ThingPtr) valuesArray);
CArray2Array(hilitesArray, hilites);
SetVar(retVal, HIGHLIGHTED, (ThingPtr) hilitesArray);
CArray2Array(locArray, loc);
SetVar(retVal, ICONLOC, locArray);
Set2DIntBounds(retVal, left, right, bottom, top);
SetVar(retVal, NAME, NewString(name));
SetVar(retVal, ORTHO, ObjFalse);
return retVal;
}
else
{
return NULLOBJ;
}
}